package com.lecture.junit.tdd.example;


import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class LoginServiceState {

    public final int ACCOUNT_TIME = 45;
    public final int PASSWORD_TIME = 30;
    AtomicInteger count;

    public void login(LoginServiceInterface context, IAccount acc, String password) {
        if (isAccountPasswordMatchesAndNotRevoked(acc, password)) {
            if (acc.isLoggedIn()) {
                throw new AccountAlreadyLoggedInException();
            }

            if (isDateExpired(acc.getLastTimePasswordChanged(), PASSWORD_TIME)) {
                throw new AccountPasswordExpiredException();
            }

            acc.setLoggedIn();
            context.setState(acc.getUserName(), new AwaitFirstLoginAttempt());
        } else {
            handlePasswordFail(context, acc);
        }
    }

    public void changePassword(LoginServiceInterface context, IAccount acc, String currentPassword, String newPassword) {
        if (isAccountPasswordMatchesAndNotRevoked(acc, currentPassword)) {

            if (!acc.changePasswords(newPassword)) {
                throw new PasswordCannotBeUsedAgainException();
            }

            context.setState(acc.getUserName(), new AwaitFirstLoginAttempt());
        } else {
            handlePasswordFail(context, acc);
        }
    }
    /**
     * Checking for correct password and is account not revoked
     * (Simply: can we work with this account with that password)
     * */
    public boolean isAccountPasswordMatchesAndNotRevoked(IAccount acc, String password) {
        if (acc.passwordMatches(password)) {
            if (acc.isRevoked()) {
                throw new AccountIsRevokedException();
            }

            if (isDateExpired(acc.getLastTimeAccountWasUsed(), ACCOUNT_TIME)) {
                throw new AccountIsOverdueException();
            }
            return true;
        }
        return false;
    }

    protected boolean isDateExpired(Calendar calendar, int date) {
        if (calendar == null) {
            return false;
        }
        calendar.add(Calendar.DATE, date);
        return Calendar.getInstance().after(calendar);
    }

    protected abstract void handlePasswordFail(LoginServiceInterface context, IAccount acc);
}
